package com.spzx.product.receiver;

import com.rabbitmq.client.Channel;
import com.spzx.common.core.utils.StringUtils;
import com.spzx.product.service.SkuStockService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import com.spzx.common.rabbit.constant.MqConst;

import java.io.IOException;


/**
 * @author Haoran Sun
 * @since 2024/08/05
 */

@Component
@Slf4j
public class ProductReceiver {

    @Resource
    private SkuStockService skuStockService;

    /**
     * 解锁库存
     * @param orderNo  订单号-自动从消息中结构出来
     * @param message  消息-Message 类是 Spring AMQP 提供的接口，用于封装来自 RabbitMQ 的消息。你可以从中获取到消息头（headers）、消息体（body）以及其他相关信息
     * @param channel  通道-Channel 是 RabbitMQ 中的基本工作单元，也是客户端和服务器之间通信的桥梁。
     *                 通过这个通道，你可以在消息处理完成后发送确认信息（acknowledgement）给 RabbitMQ，告诉它消息已经被成功处理，可以删除或释放资源
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_UNLOCK,
                    durable = "true"),
            exchange = @Exchange(value = MqConst.EXCHANGE_PRODUCT),
            key = {MqConst.ROUTING_UNLOCK}))
    public void unLock(String orderNo, Message message, Channel channel) {
        try {
            if (StringUtils.isNotEmpty(orderNo)){
                log.info("订单{}解锁库存", orderNo);
                skuStockService.unLock(orderNo);
                channel.basicAck(message.getMessageProperties().getDeliveryTag(),
                        false);
            }
        }catch (Exception e){
            try {
                channel.basicNack(message.getMessageProperties().getDeliveryTag(),
                        false,
                        true);
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
        }
    }


    /**
     * 扣减库存
     * @param orderNo  订单号
     * @param channel  通道
     *                 Channel 是 RabbitMQ 中的基本工作单元，也是客户端和服务器之间通信的桥梁。
     *                 通过这个通道，你可以在消息处理完成后发送确认信息（acknowledgement）给 RabbitMQ，告诉它消息已经被成功处理，可以删除或释放资源
     * @param message  消息-Message 类是 Spring AMQP 提供的接口，用于封装来自 RabbitMQ 的消息。你可以从中获取到消息头（headers）、消息体（body）以及其他相关信息
     */
    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(value = MqConst.EXCHANGE_PRODUCT, durable = "true"),
            value = @Queue(value = MqConst.QUEUE_MINUS, durable = "true"),
            key = {MqConst.ROUTING_MINUS}
    ))
    public void minus(String orderNo, Channel channel, Message message) {
        try {
            //业务处理
            if (StringUtils.isNotEmpty(orderNo)){
                log.info("[商品服务]监听减库存消息：{}", orderNo);
                //扣减库存
                skuStockService.minus(orderNo);
            }
            //手动应答
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            try {
                channel.basicNack(message.getMessageProperties().getDeliveryTag(),
                        false,
                        true);
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
        }
    }

}
